WPF加入Resource之語系功能


Posted by hotmaneil on 2024-04-09

Google找了一些文章,發現WPF不同於ASP.NET MVC和Windows Form使用的resx檔,而是用xaml檔。

ASP.NET MVC

Windows Form

WPF

以下會製作語系下拉選單可以選擇中英文或其它國家語言,然後介面的語言會即時變更。

首先新增資料夾Cultures並新增兩種語言:英文和繁體中文(台灣)

en-US.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="Submit">Submit</sys:String>
    <sys:String x:Key="ModifySuccess">Modify success!</sys:String>

</ResourceDictionary>

zh-TW.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="Submit">提交</sys:String>
    <sys:String x:Key="ModifySuccess">修改成功!</sys:String>

</ResourceDictionary>

檔案屬性如下圖:

Settings.settings加入名稱為DefaultCulture如下圖:

在專案目錄下找App.xaml修改如下:

<Application x:Class="CFXLibTestTool_WPF.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:CFXLibTestTool_WPF"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Cultures/en-US.xaml" x:Name="languageResource"></ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

App.xaml.cs:

/// <summary>
/// 變更語系
/// </summary>
/// <param name="culture"></param>
public void ChangeLanguage(CultureInfo culture)
{
    ResourceDictionary langRd = null;
    try
    {
        langRd = LoadComponent
                 (new Uri(@"Cultures\" + culture.Name + ".xaml ", UriKind.Relative))
                 as ResourceDictionary;
    }
    catch
    {
    }

    if (langRd != null)
    {
        if (Resources.MergedDictionaries.Count > 0)
        {
            Resources.MergedDictionaries.Clear();
        }
        Resources.MergedDictionaries.Add(langRd);
    }
}

在專案目錄下新增資料夾Helper並新增CulturesHelper.cs:

public class CulturesHelper
{
    private static bool _isFoundInstalledCultures = false;

    private static string _resourcePrefix = "";

    private static string _culturesFolder = "Cultures";


    private static List<CultureInfo> _supportedCultures = new List<CultureInfo>();

    public static List<CultureInfo> SupportedCultures
    {
        get
        {
            return _supportedCultures;
        }
    }

    public CulturesHelper()
    {
        if (!_isFoundInstalledCultures)
        {

            CultureInfo cultureInfo = new CultureInfo("");

            List<string> files = Directory.GetFiles(string.Format("{0}\\{1}", System.Windows.Forms.Application.StartupPath, _culturesFolder))
                .Where(s => s.Contains(_resourcePrefix) && s.ToLower().EndsWith("xaml")).ToList();

            foreach (string file in files)
            {
                try
                {
                    int lastIndex = file.LastIndexOf("\\");
                    string cultureName = file.Substring(lastIndex+1).Replace(".xaml", "");
                    cultureInfo = CultureInfo.GetCultureInfo(cultureName);

                    if (cultureInfo != null)
                        _supportedCultures.Add(cultureInfo);
                }
                catch (ArgumentException)
                {
                }

            }

            if (_supportedCultures.Count > 0 && Properties.Settings.Default.DefaultCulture != null)
            {
                var app = (App)App.Current;
                app.ChangeLanguage(Properties.Settings.Default.DefaultCulture);
                SaveCulture(Properties.Settings.Default.DefaultCulture);
            }
            _isFoundInstalledCultures = true;
        }
    }

    /// <summary>
    /// 儲存語系設定
    /// </summary>
    /// <param name="culture"></param>
    public static void SaveCulture(CultureInfo culture)
    {
        if (_supportedCultures.Contains(culture))
        {
            string LoadedFileName = string.Format("{0}\\{1}\\{2}.xaml", 
                System.Windows.Forms.Application.StartupPath, 
                _culturesFolder, 
                culture.Name);

            FileStream fileStream = new FileStream(@LoadedFileName, FileMode.Open);

            Properties.Settings.Default.DefaultCulture = culture;
            Properties.Settings.Default.Save();
        }
    }

}

製作語系下拉選單:MainWindow.xaml

 <Window.Resources>
     <helper:CulturesHelper x:Key="CulturesHelperDataSource" d:IsDataSource="True">
     </helper:CulturesHelper>
 </Window.Resources>

 <!-- 語系選擇 -->
 <TextBlock Foreground="Black" 
     Grid.Column="8" Grid.Row="3" FontSize="13" Text="Language:" Margin="35,8,0,0" 
     Visibility="Visible"/>
 <ComboBox Grid.Row="3" Grid.Column="9" Name="cbLanguage"
           VerticalAlignment="Center" Margin="1" FontSize="12" DisplayMemberPath="DisplayName"
           ItemsSource="{Binding SupportedCultures, Source={StaticResource CulturesHelperDataSource}}"
           SelectionChanged="cbLanguage_SelectionChanged"
           Visibility="Visible"/>
/// <summary>
/// 選擇語系
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cbLanguage_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var selected = cbLanguage.SelectedItem;

    CultureInfo cultureInfo = new CultureInfo("");
    cultureInfo = CultureInfo.GetCultureInfo(selected.ToString());

    var app = (App)App.Current;
    app.ChangeLanguage(cultureInfo);
}

在任何地方的xaml使用DynamicResource:

<!-- 按鈕 -->
<Button Grid.Column="1" Grid.Row="10" Cursor="Hand" Name="btnSubmit" Click="btnSubmit_Click" Content="{DynamicResource Submit}"></Button>

或是在後置程式碼的用法如下:

 Application.Current.Resources["ModifySuccess"];

參考文章:

https://dotblogs.com.tw/ouch1978/2011/07/29/wpf-globalization-resourcedictionary
https://www.dotblogs.com.tw/MemoryRecall/2021/07/12/170544
https://wpf-tutorial.com/zh/12/wpf%E6%87%89%E7%94%A8%E7%A8%8B%E5%BC%8F/%E8%B3%87%E6%BA%90resources/


#wpf #語系







Related Posts

後端好朋友 Express middleware

後端好朋友 Express middleware

create react app 專案 git push 推不上 remote repo

create react app 專案 git push 推不上 remote repo

寬鬆相等、嚴格相等以及隱含轉型

寬鬆相等、嚴格相等以及隱含轉型


Comments